package io;
import io.Prescription.BgColour;
import io.Prescription.Dimensions;
import io.Prescription.PrescriptionObjects;import io.Prescription.PrescriptionObjects.FillColour;
import io.Prescription.PrescriptionObjects.TextColour;
import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import model.PrescriptionBox;
import model.PrescriptionLabel;import model.PrescriptionObject;/** * A class to encapsulate the parsing of XML * @author Mohammed Abdullah */
public class xmlParser {
	private static xmlParser instance;
	private JAXBContext context;
	private Color LineColour;
	private Color FillColour;
	private Color TextColour;
	private model.Prescription prescription;
	private io.Prescription apiP;
	private xmlParser(){
		try{
			context = JAXBContext.newInstance(io.Prescription.class);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		prescription = model.Prescription.getInstance();
	}
	public static xmlParser getInstance(){
		if(instance == null){
			instance = new xmlParser();
		}
		return instance;
	}
	/**
	 * This method reads an XML file at a file location defined in the parameter
	 * and converts it to a view.Prescription object and returns it to the user
	 * 
	 * @param fileName - The filename of the XML file to load
	 * @return - Prescription object to return
	 */
	public void load(String fileName){
		prescription.clear();
		prescription = model.Prescription.getInstance();
		try {
			Unmarshaller u = context.createUnmarshaller();
			apiP = (Prescription) u.unmarshal(new FileInputStream(fileName));
			prescription.setName(apiP.getName());
			prescription.setWidth(apiP.getDimensions().getWidth());
			prescription.setHeight(apiP.getDimensions().getHeight());
			prescription.setSerialNumber(apiP.getSerialNo());
			// Set the background colour
			prescription.setBGColour(apiP.getBgColour().getRed(),
					apiP.getBgColour().getGreen(),
					apiP.getBgColour().getBlue());
			for(Prescription.PrescriptionObjects obj : apiP.getPrescriptionObjects()){
				if(obj.getObjectType().equals("PrescriptionBox")){
					LineColour = new Color(obj.getLineColour().getRed(),
							obj.getLineColour().getGreen(),
							obj.getLineColour().getBlue());
					FillColour = new Color(obj.getFillColour().getRed(),
							obj.getFillColour().getGreen(),
							obj.getFillColour().getBlue());
					TextColour = new Color(obj.getTextColour().getRed(),
							obj.getTextColour().getGreen(),
							obj.getTextColour().getBlue());
					PrescriptionBox box = new PrescriptionBox(obj.getPosition().getX(),
							obj.getPosition().getY(),
							obj.getDimensions().getHeight(),
							obj.getDimensions().getWidth(),
							LineColour,
							FillColour,
							TextColour,
							obj.getLineWidth(),
							obj.getName(),
							obj.isTransparent());					box.setPlaceholder(obj.getPlaceholder());
					box.setTransparent(obj.isTransparent());
					box.setLineWidth(obj.getLineWidth());
					prescription.addObject(box);
					// adding box sets to changed but we just loaded file in so must set unchanged
					prescription.setUnchanged();
				}else if(obj.getObjectType().equals("PrescriptionLabel")){					LineColour = new Color(obj.getLineColour().getRed(),							obj.getLineColour().getGreen(),							obj.getLineColour().getBlue());					FillColour = new Color(obj.getFillColour().getRed(),							obj.getFillColour().getGreen(),							obj.getFillColour().getBlue());					TextColour = new Color(obj.getTextColour().getRed(),							obj.getTextColour().getGreen(),							obj.getTextColour().getBlue());					PrescriptionLabel label = new PrescriptionLabel(obj.getPosition().getX(),							obj.getPosition().getY(),							obj.getDimensions().getHeight(),							obj.getDimensions().getWidth(),							LineColour,							obj.getLineWidth(),							obj.getName(),							FillColour,							TextColour);					label.setPlaceholder(obj.getPlaceholder());					label.setTransparent(obj.isTransparent());					label.setLineWidth(obj.getLineWidth());					prescription.addObject(label);					// adding box sets to changed but we just loaded file in so must set unchanged					prescription.setUnchanged();				}
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		//return pres;
	}	/**	 * Saves the prescription as XML format	 * @param prescription the prescription to save as XML	 * @param fileName the name of the file to be named	 */
	public void saveXML(model.Prescription prescription, String fileName){
		try {
			//JAXBContext context = JAXBContext.newInstance(api.Prescription.class);
			Marshaller m = context.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			/*
			 * Here a new prescription object will be created with all the details
			 * of the existing one on the canvas. This will allow it to be in the
			 * suitable form for the JAXB to create an XML file for.
			 */
			//Create a new temporary prescription object for JAXB
			io.Prescription obj = new io.Prescription();
			//Set the name for the prescription
			obj.setName(prescription.getName());
			//Set the Background Colour
			BgColour bgColour = new BgColour();
			bgColour.setRed(prescription.getBGColour().getRed());
			bgColour.setGreen(prescription.getBGColour().getGreen());
			bgColour.setBlue(prescription.getBGColour().getBlue());
			obj.setBgColour(bgColour);
			//Set the Serial Number
			obj.setSerialNo(prescription.getSerialNo());
			Dimensions dimensions = new Dimensions();
			dimensions.setWidth(prescription.getWidth());
			dimensions.setHeight(prescription.getHeight());
			obj.setDimensions(dimensions);
			//Add the objects in the prescription
			for(PrescriptionObject object : prescription.objects()){
				PrescriptionObjects pObject = new PrescriptionObjects();				
				if(object instanceof PrescriptionBox){
					int x = object.getX();
					int y = object.getY();
					int width = object.getWidth();
					int height = object.getHeight();					String placeholder = ((PrescriptionBox) object).getPlaceholder();
					boolean in = false;					//Check if the box is within the bounds of the prescription. Resize if needed
					if(((x > 0 && x < prescription.getWidth())||
							((x + width) > 0 && (x + width) < prescription.getWidth())) &&
							((y > 0 && y < prescription.getHeight()) ||
									((y + height) > 0) && (y + width) < prescription.getHeight())
					){
						if(x > 0 && (x + width) > 0 && y > 0 && (y + height) > 0 &&
								x < prescription.getWidth() && y < prescription.getHeight()) //If the whole object is within bounds
						{
							in = true;
						}
						if(x < 0 && (x + width) > 0){ //if just the x is smaller than 0
							int diff = 0 - x;
							width = width - diff;
							object.setX(0);
							object.setWidth(width);
							in = true;
						}
						if(y < 0 && (y + height) > 0){ //if the y is smaller than 0 set to 0
							int diff = 0 - y;
							height = height - diff;
							object.setY(0);
							object.setHeight(height);
							in = true;
						}
						if(x > 0 && (x + width) > prescription.getWidth()){ // if width is more than prescription width
							object.setWidth(prescription.getWidth() - object.getX());
							in = true;
						}
						if(y > 0 && (y + height) > prescription.getHeight()){ // if height is more than prescription height
							object.setHeight(prescription.getHeight() - object.getY());
							in = true;
						}
					}
					if(x < 0 && (x + width) > prescription.getWidth()){
						object.setX(0);
						object.setWidth(prescription.getWidth() - object.getX());
						in = true;
					}
					if(y < 0 && (y + height) > prescription.getHeight()){
						object.setY(0);
						object.setHeight(prescription.getHeight() - object.getY());
						in = true;
					}
					if(in){ //If the box is completly within the bounds of the prescription
						//Name of object e.g. Address, D.O.B, Signature etc.
						pObject.setName(((PrescriptionBox) object).getName());
						//Type of object e.g. PrescriptionBox or PrescriptionLine
						pObject.setObjectType("PrescriptionBox");												pObject.setPlaceholder(placeholder);
						//Set the fill colour of object
						FillColour fc = new FillColour();
						fc.setRed(object.getFillColourRed());
						fc.setGreen(object.getFillColourGreen());
						fc.setBlue(object.getFillColourBlue());
						pObject.setFillColour(fc);
						pObject.setLineWidth(object.getLineWidth());
						//Set the text Colour of object
						TextColour tc= new TextColour();
						tc.setRed(object.getTextColourRed());
						tc.setGreen(object.getTextColourGreen());
						tc.setBlue(object.getTextColourBlue());
						pObject.setTextColour(tc);
						//Set whether the box is transparent or not
						pObject.setTransparent(object.isTransparent());
						//Set the dimensions of object
						PrescriptionObjects.Dimensions d1 = new PrescriptionObjects.Dimensions();
						d1.setWidth(object.getWidth());
						d1.setHeight(object.getHeight());
						pObject.setDimensions(d1);
						//Set the position of object
						PrescriptionObjects.Position pos1 = new PrescriptionObjects.Position();
						pos1.setX(object.getX());
						pos1.setY(object.getY());
						pObject.setPosition(pos1);

						PrescriptionObjects.LineColour lc = new PrescriptionObjects.LineColour();
						lc.setRed(object.getLineColourRed());
						lc.setGreen(object.getLineColourGreen());
						lc.setBlue(object.getLineColourBlue());

						pObject.setLineColour(lc);

						obj.getPrescriptionObjects().add(pObject);
					}
				}else if(object instanceof PrescriptionLabel){					int x = object.getX();					int y = object.getY();					int width = object.getWidth();					int height = object.getHeight();					String placeholder = ((PrescriptionLabel) object).getPlaceholder();					boolean in = false;					//Check if the box is within the bounds of the prescription. Resize if needed					if(((x > 0 && x < prescription.getWidth())||							((x + width) > 0 && (x + width) < prescription.getWidth())) &&							((y > 0 && y < prescription.getHeight()) ||									((y + height) > 0) && (y + width) < prescription.getHeight())					){						if(x > 0 && (x + width) > 0 && y > 0 && (y + height) > 0 &&								x < prescription.getWidth() && y < prescription.getHeight()) //If the whole object is within bounds						{							in = true;						}						if(x < 0 && (x + width) > 0){ //if just the x is smaller than 0							int diff = 0 - x;							width = width - diff;							object.setX(0);							object.setWidth(width);							in = true;						}						if(y < 0 && (y + height) > 0){ //if the y is smaller than 0 set to 0							int diff = 0 - y;							height = height - diff;							object.setY(0);							object.setHeight(height);							in = true;						}						if(x > 0 && (x + width) > prescription.getWidth()){ // if width is more than prescription width							object.setWidth(prescription.getWidth() - object.getX());							in = true;						}						if(y > 0 && (y + height) > prescription.getHeight()){ // if height is more than prescription height							object.setHeight(prescription.getHeight() - object.getY());							in = true;						}					}					if(x < 0 && (x + width) > prescription.getWidth()){						object.setX(0);						object.setWidth(prescription.getWidth() - object.getX());						in = true;					}					if(y < 0 && (y + height) > prescription.getHeight()){						object.setY(0);						object.setHeight(prescription.getHeight() - object.getY());						in = true;					}					if(in){ //If the box is completly within the bounds of the prescription						//Name of object e.g. Address, D.O.B, Signature etc.						pObject.setName(((PrescriptionLabel) object).getName());						//Type of object e.g. PrescriptionBox or PrescriptionLine						pObject.setObjectType("PrescriptionLabel");												pObject.setPlaceholder(placeholder);						//Set the fill colour of object						FillColour fc = new FillColour();						fc.setRed(object.getFillColourRed());						fc.setGreen(object.getFillColourGreen());						fc.setBlue(object.getFillColourBlue());						pObject.setFillColour(fc);						pObject.setLineWidth(object.getLineWidth());						//Set the text Colour of object						TextColour tc= new TextColour();						tc.setRed(object.getTextColourRed());						tc.setGreen(object.getTextColourGreen());						tc.setBlue(object.getTextColourBlue());						pObject.setTextColour(tc);						//Set whether the box is transparent or not						pObject.setTransparent(object.isTransparent());						//Set the dimensions of object						PrescriptionObjects.Dimensions d1 = new PrescriptionObjects.Dimensions();						d1.setWidth(object.getWidth());						d1.setHeight(object.getHeight());						pObject.setDimensions(d1);						//Set the position of object						PrescriptionObjects.Position pos1 = new PrescriptionObjects.Position();						pos1.setX(object.getX());						pos1.setY(object.getY());						pObject.setPosition(pos1);						PrescriptionObjects.LineColour lc = new PrescriptionObjects.LineColour();						lc.setRed(object.getLineColourRed());						lc.setGreen(object.getLineColourGreen());						lc.setBlue(object.getLineColourBlue());						pObject.setLineColour(lc);						obj.getPrescriptionObjects().add(pObject);					}				}												
			}

			try {
				m.marshal(obj, new FileOutputStream(fileName));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}
}